package org.steven.crm.core.utils.http;

import com.steven.common.utils.MD5Util;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@SuppressWarnings("deprecation")
public class SimpleHttpClient {
//	private static Logger logger = Logger.getLogger(HttpSend.class);
	private static final int DEFAULT_CONNECT_TIME_OUT = 20 * 1000;
	private static final int DEFAULT_SOCKET_TIME_OUT = 20 * 1000;

	public static String get(String strUrl, String param) {
		return get(strUrl, param, null,-1, -1);
	}

	public static String get(String strUrl, String param, Map<String, String> headerMap) {
		return get(strUrl, param, headerMap,-1, -1);
	}
	
	public static String get(String strUrl, String param, int connectionTimeout, int socketTimeout) {
		return get(strUrl, param, null, connectionTimeout, socketTimeout);
	}

	public static String get(String strUrl, String param, Map<String, String> headerMap, int connectionTimeout, int socketTimeout) {
		CloseableHttpClient httpClient = HttpConnectionManager.getInstance().getHttpClient();
		HttpGet get = new HttpGet(strUrl + ((param == null || param.equals("")) ? "" : ("?" + param)));

		RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
		if (connectionTimeout > 0) {
			requestConfigBuilder = requestConfigBuilder.setConnectTimeout(connectionTimeout);
		}
		if (socketTimeout > 0) {
			requestConfigBuilder = requestConfigBuilder.setSocketTimeout(socketTimeout);
		}
		RequestConfig defaultRequestConfig = requestConfigBuilder.build();
		get.setConfig(defaultRequestConfig);

		String result = "";
		CloseableHttpResponse response = null;
		try {
//			get.setHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36");

			if (null != headerMap && !headerMap.isEmpty()) {
				Iterator<String> headerIter = headerMap.keySet().iterator();
				while (headerIter.hasNext()) {
					String headerKey = headerIter.next();
					String headerValue = headerMap.get(headerKey);
					get.setHeader(headerKey, headerValue);
				}
			}

			response = httpClient.execute(get);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				InputStream in = response.getEntity().getContent();
				result = IOUtils.toString(in);
				in.close();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	public static String post(String strUrl, Map<String, String> params) {
		return post(strUrl, params, null, -1, -1);
	}

	public static String post(String strUrl, Map<String, String> params, Map<String, String> headerMap) {
		return post(strUrl, params, headerMap, -1, -1);
	}

	public static String post(String strUrl, Map<String, String> params, int connectionTimeout, int socketTimeout) {
		return post(strUrl, params, null, connectionTimeout, socketTimeout);
	}

	public static String post(String strUrl, Map<String, String> params, Map<String, String> headerMap,
							  int connectionTimeout, int socketTimeout) {
		CloseableHttpClient httpClient = HttpConnectionManager.getInstance().getHttpClient();
		HttpPost post = new HttpPost(strUrl);

		RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
		if (connectionTimeout > 0) {
			requestConfigBuilder = requestConfigBuilder.setConnectTimeout(connectionTimeout);
		}
		if (socketTimeout > 0) {
			requestConfigBuilder = requestConfigBuilder.setSocketTimeout(socketTimeout);
		}
		RequestConfig defaultRequestConfig = requestConfigBuilder.build();
		post.setConfig(defaultRequestConfig);

		String result = "";
		CloseableHttpResponse response = null;
		try {
//			post.setHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36");
			if (null != headerMap && !headerMap.isEmpty()) {
				Iterator<String> headerIter = headerMap.keySet().iterator();
				while (headerIter.hasNext()) {
					String headerKey = headerIter.next();
					String headerValue = headerMap.get(headerKey);
					post.setHeader(headerKey, headerValue);
				}
			}

			if (null != params && !params.isEmpty()) {
				ArrayList<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>();
				Iterator<String> iter = params.keySet().iterator();
				while (iter.hasNext()) {
					String key = iter.next();
					String value = params.get(key);
					parameters.add(new BasicNameValuePair(key, value));
				}
				post.setEntity(new UrlEncodedFormEntity(parameters));
			}

			response = httpClient.execute(post);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				InputStream in = response.getEntity().getContent();
				result = IOUtils.toString(in);
				in.close();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	public static String postWithFile(String url, Map<String, String> headerMap, File bodyMap) throws IOException {
		return postWithFile(url, headerMap, bodyMap, DEFAULT_CONNECT_TIME_OUT, DEFAULT_SOCKET_TIME_OUT);
	}

	public static String postWithFile(String url, Map<String, String> headerMap, File file,
								  int connectionTimeout, int socketTimeout) throws IOException {
		CloseableHttpClient httpClient = HttpClients.createDefault();
		String result = "";
		CloseableHttpResponse response = null;
		try {
			HttpPost httpPost = new HttpPost(url);
			RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
			if (connectionTimeout > 0) {
				requestConfigBuilder = requestConfigBuilder.setConnectTimeout(connectionTimeout);
			}
			if (socketTimeout > 0) {
				requestConfigBuilder = requestConfigBuilder.setSocketTimeout(socketTimeout);
			}
			RequestConfig defaultRequestConfig = requestConfigBuilder.build();
			httpPost.setConfig(defaultRequestConfig);

			if (null != headerMap && !headerMap.isEmpty()) {
				Iterator<String> headerIter = headerMap.keySet().iterator();
				while (headerIter.hasNext()) {
					String headerKey = headerIter.next();
					String headerValue = headerMap.get(headerKey);
					httpPost.setHeader(headerKey, headerValue);
				}
			}

			/*MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
			if (bodyMap != null) {
				bodyMap.forEach((key, value) -> entityBuilder.addBinaryBody(key,  value,
						ContentType.DEFAULT_BINARY, value.getName()));
			}
			HttpEntity reqEntity = entityBuilder.setCharset(CharsetUtils.get("UTF-8")).build();
			httpPost.setEntity(reqEntity);*/
			byte[] bytes = FileUtils.readFileToByteArray(file);
			httpPost.setEntity(new ByteArrayEntity(bytes));

			response = httpClient.execute(httpPost);
			if (response.getEntity() != null) {
				InputStream in = response.getEntity().getContent();
				if (in != null) {
					result = IOUtils.toString(in);
					in.close();
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}
	
	public static String postWithJson(String url, String jsonStr) {
		return postWithJson(url, jsonStr, null, DEFAULT_CONNECT_TIME_OUT, DEFAULT_SOCKET_TIME_OUT);
	}

	public static String postWithJson(String url, Map<String, String> headerMap, String jsonStr) {
		return postWithJson(url, jsonStr, headerMap, DEFAULT_CONNECT_TIME_OUT, DEFAULT_SOCKET_TIME_OUT);
	}
	
	public static String postWithJson(String url, String jsonStr, Map<String, String> headerMap,
									  int connectionTimeout, int socketTimeout) {
		CloseableHttpClient httpClient = HttpConnectionManager.getInstance().getHttpClient();
		
		HttpPost post = new HttpPost(url);
		RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
		if (connectionTimeout > 0) {
			requestConfigBuilder = requestConfigBuilder.setConnectTimeout(connectionTimeout);
		}
		if (socketTimeout > 0) {
			requestConfigBuilder = requestConfigBuilder.setSocketTimeout(socketTimeout);
		}
		RequestConfig defaultRequestConfig = requestConfigBuilder.build();
		post.setConfig(defaultRequestConfig);
		
		String result = "";
		CloseableHttpResponse response = null;
		try {
			if (null != headerMap && !headerMap.isEmpty()) {
				Iterator<String> headerIter = headerMap.keySet().iterator();
				while (headerIter.hasNext()) {
					String headerKey = headerIter.next();
					String headerValue = headerMap.get(headerKey);
					post.setHeader(headerKey, headerValue);
				}
			}

			StringEntity s = new StringEntity(jsonStr, "UTF-8");
			s.setContentType("application/json");
			post.setEntity(s);


			response = httpClient.execute(post);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				 InputStream in = response.getEntity().getContent();
				 result = IOUtils.toString(in, "UTF-8");
				 in.close();
			} else {
				InputStream in = response.getEntity().getContent();
				 result = IOUtils.toString(in, "UTF-8");
				 in.close();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	public static String putWithJson(String url, String jsonStr) {
		return putWithJson(url, jsonStr, null, DEFAULT_CONNECT_TIME_OUT, DEFAULT_SOCKET_TIME_OUT);
	}

	public static String putWithJson(String url, Map<String, String> headerMap, String jsonStr) {
		return putWithJson(url, jsonStr, headerMap, DEFAULT_CONNECT_TIME_OUT, DEFAULT_SOCKET_TIME_OUT);
	}

	public static String putWithJson(String url, String jsonStr, Map<String, String> headerMap,
									  int connectionTimeout, int socketTimeout) {
		CloseableHttpClient httpClient = HttpConnectionManager.getInstance().getHttpClient();

		HttpPut put = new HttpPut(url);
		RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
		if (connectionTimeout > 0) {
			requestConfigBuilder = requestConfigBuilder.setConnectTimeout(connectionTimeout);
		}
		if (socketTimeout > 0) {
			requestConfigBuilder = requestConfigBuilder.setSocketTimeout(socketTimeout);
		}
		RequestConfig defaultRequestConfig = requestConfigBuilder.build();
		put.setConfig(defaultRequestConfig);

		String result = "";
		CloseableHttpResponse response = null;
		try {
			if (null != headerMap && !headerMap.isEmpty()) {
				Iterator<String> headerIter = headerMap.keySet().iterator();
				while (headerIter.hasNext()) {
					String headerKey = headerIter.next();
					String headerValue = headerMap.get(headerKey);
					put.setHeader(headerKey, headerValue);
				}
			}

			StringEntity s = new StringEntity(jsonStr, "UTF-8");
			s.setContentType("application/json");
			put.setEntity(s);


			response = httpClient.execute(put);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				InputStream in = response.getEntity().getContent();
				result = IOUtils.toString(in, "UTF-8");
				in.close();
			} else {
				InputStream in = response.getEntity().getContent();
				result = IOUtils.toString(in, "UTF-8");
				in.close();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	private static class HttpConnectionManager {
		private static HttpConnectionManager instance = new HttpConnectionManager();
		private HttpConnectionManager() {
			init();
		}

		PoolingHttpClientConnectionManager cm = null;

		private void init() {
			LayeredConnectionSocketFactory sslsf = null;
			try {
				sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault());
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			}


			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
					.register("https", sslsf)
					.register("http", new PlainConnectionSocketFactory())
					.build();
			cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
			cm.setMaxTotal(200);
//        cm.setDefaultMaxPerRoute(50);
		}

		public static HttpConnectionManager getInstance() {
			return instance;
		}

		public CloseableHttpClient getHttpClient() {
			CloseableHttpClient httpClient = HttpClients.custom()
					.setConnectionManager(cm)
					.build();
			return httpClient;
		}
	}

	public static void main(String[] args) throws Exception {
		Map<String, String> requestParas = new HashMap<>();
		String timestamp = System.currentTimeMillis() + "";
		String method = "DeviceService.getDeviceAcessToken";
		requestParas.put("method", method);
		requestParas.put("timestamp", timestamp);
		requestParas.put("module", "router");
		requestParas.put("action", "rest");
		String sign = getHqApiSign(method, timestamp, "98jh4467811fcb4b97be3asfdqwefa7d5ad5d23a4");
		requestParas.put("sign", sign);

		String requestParams = new String();
		Iterator<String> iterator = requestParas.keySet().iterator();
		while (iterator.hasNext()) {
			String key = iterator.next();
			String value = requestParas.get(key);
			requestParams += "&" + key + "=" + value;
		}
		requestParams = requestParams.replaceFirst("&", "");

		String responseStr = SimpleHttpClient.get("http://hq.ankangshu.com/router", requestParams, null);
		System.out.println(responseStr);
	}

	private static String getHqApiSign(String method, String timestamp, String privateKey) throws Exception {
		String orgin = "method" + method + "timestamp" + timestamp + privateKey;
		return MD5Util.MD5(orgin);
	}
}
